/*
 * Copyright (c) 2007 jNetX.
 * http://www.jnetx.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * jNetX. You shall not disclose such Confidential Information and
 * shall use it only in accordance with the terms of the license
 * agreement you entered into with jNetX.
 *
 * $Id$
 */
package com.jnetx.javax.sip.address;

import com.jnetx.javax.sip.util.ByteArrayUtil;

import javax.sip.address.*;
import java.text.ParseException;

/**
 * This factory provides methods that allow an application to create
 * Address objects, URI's, SipURI's and TelURL's from a particular
 * implementation of this specification. This class is a singleton and can be
 * retrieved from the {@link javax.sip.SipFactory#createAddressFactory()}.
 *
 * @author <a href="mailto:dparhonin@jnetx.ru">Dmitry Parhonin</a>
 * @version $Revision$
 */
public class AddressFactoryImpl implements AddressFactory {

    /**
     * Creates a URI based on given URI string. The URI string is parsed in
     * order to create the new URI instance. Depending on the scheme the
     * returned may or may not be a SipURI or TelURL cast as a URI.
     *
     * @param uri the new string value of the URI.
     * @throws java.text.ParseException if the URI string is malformed.
     */
    public URI createURI(String uri) throws ParseException {
        if (uri == null || uri.equals(""))
            throw new ParseException("The provided URI is malformed! uri='" + uri + "'", 0);
        return createURILazily(uri);
    }

    /**
     * Creates a SipURI based on the given user and host components. The user
     * component may be null.
     * <p/>
     * This create method first builds a URI in string form using the given
     * components as follows:
     * <ul>
     * <li>Initially, the result string is empty.
     * <li>The scheme followed by a colon character ('sip:') is appended to
     * the result.
     * <li>The user and host are then appended. Any character that is not a
     * legal URI character is quoted.
     * </ul>
     * <br>
     * The resulting URI string is then parsed in order to create the new
     * SipURI instance as if by invoking the createURI(String) constructor;
     * this may cause a URISyntaxException to be thrown.
     * <p/>
     * An application that wishes to create a 'sips' URI should call the
     * {@link javax.sip.address.SipURI#setSecure(boolean)} with an argument of 'true' on the
     * returned SipURI.
     *
     * @param user - the new string value of the user, this value may be null.
     * @param host - the new string value of the host.
     * @throws java.text.ParseException if the URI string is malformed.
     */
    public SipURI createSipURI(String user, String host) throws ParseException {
        return new SipURIImpl(user, host);
    }

    /**
     * Creates a TelURL based on given URI string. The scheme should
     * not be included in the phoneNumber string argument.
     *
     * @param phoneNumber the new string value of the phoneNumber.
     * @throws java.text.ParseException if the URI string is malformed.
     */
    public TelURL createTelURL(String phoneNumber) throws ParseException {
        return new TelURLImpl(phoneNumber);
    }

    /**
     * Creates an Address with the new address string value. The address
     * string is parsed in order to create the new Address instance.
     * Valid arguments obey the syntax for <code>name-addr</code> tokens in
     * RFC3261, for example "Bob <sip:bob@biloxi.com>".  It is recommended to
     * use the to use the name-addr form containing '<' '>' to avoid confusion
     * of URI parameters. As a special case, the
     * string argument "*" creates a wildcard Address object with the property
     * that <code>((SipURI)Address.getURI()).getUser()</code> returns a
     * String contain one character "*".
     *
     * @param address the new string value of the address.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the address value.
     */
    public Address createAddress(String address) throws ParseException {
        final byte[] bytes = address.getBytes();
        return AddressFactoryImpl.createAddressLazily(bytes, 0, bytes.length);
    }

    /**
     * Creates an Address with the new URI attribute value.
     *
     * @param uri the URI value of the address.
     */
    public Address createAddress(URI uri) {
        AddressImpl address = new AddressImpl();
        address.setURI(uri);
        return address;
    }

    /**
     * Creates an Address with the new display name and URI attribute
     * values.
     *
     * @param displayName the new string value of the display name of the
     *                    address. A <code>null</code> value does not set the display name.
     * @param uri         the new URI value of the address.
     * @throws java.text.ParseException which signals that an error has been reached
     *                                  unexpectedly while parsing the displayName value.
     */
    public Address createAddress(String displayName, URI uri) throws ParseException {
        AddressImpl address = new AddressImpl();
        address.setDisplayName(displayName);
        address.setURI(uri);
        return address;
    }

    public static final Address createAddressLazily(byte[] data, int start, int end) throws ParseException {
        return AddressImpl.createLazily(data, start, end);
    }

    public static final Address createAddress() {
        return new AddressImpl();
    }

    public static final URI createURILazily(String uri) throws ParseException {
        final byte[] bytes = uri.getBytes();
        return createURILazily(bytes, 0, bytes.length);
    }

    public static final URI createURILazily(byte[] data, int start, int end) throws ParseException {
        int index = ByteArrayUtil.firstOccurence(data, ':', start, end);
        if (index == -1) throw new ParseException("Cannot recognize an URI scheme!", 0);
        final String scheme = new String(data, start, index - start);
        if (scheme.equals("sip") || scheme.equals("sips"))
            return SipURIImpl.createLazily(data, start, end);
        else if (scheme.equals("tel"))
            return TelURLImpl.createLazily(data, start, end);
        else if (scheme.equals("http") || scheme.equals("https"))
            return HttpURIImpl.createLazily(data, start, end);
        else if (scheme.equals("mailto"))
            return MailtoURIImpl.createLazily(data, start, end);
        else
            throw new ParseException("Cannot recognize the URI scheme: " + scheme, 0);
    }
}
/*
 * $Log$
 */